#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDebug>
#include <QString>
#include <QFile>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setFixedSize(630, 320);   //设置窗口大小
    list_model = new QStandardItemModel();  //用于和QTabView绑定
    ui->oTableView->setModel(list_model);   //绑定

    tableInit();    //表格初始化显示

    ui->btn_makeNewName->setEnabled(true); //生成新文件名 按钮可用
    //连接 表格行内容被修改后, 执行槽函数
    connect(list_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(tabRowValueChanged(QModelIndex,QModelIndex)));
}

MainWindow::~MainWindow()
{
    delete ui;
}
//根据选择的文件的文件名列表, 生成文件数据类列表
void MainWindow::create_fileList(QList<QString> &fileNameList)
{
    QList<QString>::iterator i;   //传入的文件名列表的迭代器
    for (i=fileNameList.begin(); i!=fileNameList.end(); ++i) { //遍历文件名列表
        QList<FileData>::const_iterator i_fileList; //fileList 的迭代器
        //遍历列表, 用于去重 若列表中已有该文件, 则不重复添加
        for (i_fileList=fileList.begin(); i_fileList!=fileList.end(); ++i_fileList) {
            if ((*i) == (*i_fileList).pathSrc) {
                break;
            }
        }
        if (i_fileList != fileList.end()) { //要添加的文件已存在于列表. 不重复添加
            continue;
        }
        //找到最后一个 '/', 得到 name_src 和 path_tmp
        int tmp_num = (*i).lastIndexOf("/");
        if (tmp_num == -1) { //无'/'
            continue;
        }
        FileData tmp_fileData(*i); //生成临时元素
        tmp_fileData.pathTmp = (*i).mid(0, tmp_num); //赋值 path_tmp
        QString tmp_name((*i).mid(tmp_num+1));  //临时保存文件名
        //根据 '.' 分割, 得到 文件名 和 文件后缀
        tmp_num = tmp_name.lastIndexOf(".");
        if (tmp_num != -1) {  //该文件名有类型后缀(eg: .txt)
            tmp_fileData.fileType = tmp_name.mid(tmp_num+1); //将文件类型放入
        }
        tmp_fileData.nameSrc = tmp_name.mid(0, tmp_num);  //将文件名放入
        fileList << tmp_fileData;    //在列表中添加该元素
    }
}
//打印QList<QString>
void MainWindow::printList(const QList<QString> &list)
{
    QList<QString>::const_iterator i;
    for (i=list.begin(); i!=list.end(); ++i) {
        qDebug() << (*i);
    }
}
//打印QList<FileData>
void MainWindow::printList(const QList<FileData> &list)
{
    QList<FileData>::const_iterator i;
    for (i=list.begin(); i!=list.end(); ++i) {
        qDebug() << "path_src:" << (*i).pathSrc;
        qDebug() << "path_tmp:" << (*i).pathTmp;
        qDebug() << "path_dest:" << (*i).pathDest;
        qDebug() << "name_src:" << (*i).nameSrc;
        qDebug() << "name_dest:" << (*i).nameDest;
        qDebug() << "file_type:" << (*i).fileType;
    }
}
//改变表格显示内容(原理上就是改变与表格绑定的 list_model)
void MainWindow::updateTable()
{
    list_model->clear();    //先清除
    tableInit();    //表格初始化显示
    QList<FileData>::const_iterator i_fileList;  //fileList 的const迭代器
    int rowNum = 0;    //行号
    for (i_fileList=fileList.begin(); i_fileList!=fileList.end(); ++i_fileList) { //遍历整个文件数据列表
        list_model->setItem(rowNum, 0, new QStandardItem((*i_fileList).nameSrc)); //设置第rowNum行, 第0列的元素内容
        list_model->setItem(rowNum, 1, new QStandardItem((*i_fileList).nameDest));
        list_model->setItem(rowNum, 2, new QStandardItem((*i_fileList).fileType));
        list_model->setItem(rowNum, 3, new QStandardItem(QString(" ")));
        rowNum++;
    }
}
//表格初始化显示
void MainWindow::tableInit()
{
	list_model->setHorizontalHeaderItem(0, new QStandardItem(tr("source file name")));
    list_model->setHorizontalHeaderItem(1, new QStandardItem(tr("dest file name")));
    list_model->setHorizontalHeaderItem(2, new QStandardItem(tr("file suffix")));
    list_model->setHorizontalHeaderItem(3, new QStandardItem(tr("status")));
    ui->oTableView->setSelectionMode(QAbstractItemView::ExtendedSelection); //可复选
    ui->oTableView->setSelectionBehavior(QAbstractItemView::SelectRows);    //整行选中
    ui->oTableView->setEditTriggers(QAbstractItemView::DoubleClicked);  //双击进行编辑
    ui->oTableView->horizontalHeader()->setStretchLastSection(true); //最后一列自动和右边界对齐
    ui->oTableView->setAlternatingRowColors(true);  //交替行颜色
    //设置每列的大小
    ui->oTableView->setColumnWidth(0, 200);
    ui->oTableView->setRowHeight(0, 20);
    ui->oTableView->setColumnWidth(1, 200);
    ui->oTableView->setRowHeight(1, 20);
    ui->oTableView->setColumnWidth(2, 100);
    ui->oTableView->setRowHeight(2, 20);
}
//获取当前多选的表格项的行号, 排序去重后存于rowList中
void MainWindow::rowList_update()
{
    rowList.clear();    //每次多选时, 清除上一次多选的结果
    QItemSelectionModel *selectModel = ui->oTableView->selectionModel();
    QModelIndexList indexList = selectModel->selectedIndexes(); //选择的单元的Model列表
    QModelIndexList::const_iterator i_indexList;    //indexList的迭代器
    for (i_indexList=indexList.begin(); i_indexList!=indexList.end(); ++i_indexList) {
        //qDebug() << "activated_(column, row) :" <<(*i_indexList).row();
        QList<int>::iterator i_rowList; //rowList的迭代器
        //遍历被选中行的列表, 看是否已包含, (防止重复)
        for (i_rowList=rowList.begin(); i_rowList!=rowList.end(); ++i_rowList) {
            if ((*i_rowList) == (*i_indexList).row()) {
                break;
            }
        }
        if (i_rowList == rowList.end()) {  //无重复的, 则添加进列表
            rowList << (*i_indexList).row();
        }
    }
    qSort(rowList.begin(), rowList.end());  //按从小到大进行排序
}
//根据文件数据列表中的nameDest, 生成pathDest
void MainWindow::nameDest_2_pathDest()
{
    QList<FileData>::iterator i_fileList;
    for (i_fileList=fileList.begin(); i_fileList!=fileList.end(); ++i_fileList) { //遍历文件数据列表
        if ((*i_fileList).nameDest.isEmpty()) { //新文件名为空, 则不生成pathDest
            continue;
        }
        (*i_fileList).pathDest = (*i_fileList).pathTmp + '/' + (*i_fileList).nameDest + '.' + (*i_fileList).fileType;
        //qDebug() << "path_dest" << (*i_fileList).pathDest;
    }
}

//信号-槽 单击-添加文件按钮
void MainWindow::on_btn_addFile_clicked()
{
    QList<QString>fileNameList = QFileDialog::getOpenFileNames(this);
    create_fileList(fileNameList); //将选择的文件路径分解, 存于列表中
    //print_List(file_list);  //打印列表
    updateTable();  //改变表格显示内容
}
//信号-槽 单击-移除文件按钮
void MainWindow::on_btn_deleteFile_clicked()
{
    rowList_update();   //获取当前多选, 存于rowList列表中
    QList<int>::iterator i_rowList; // rowList 列表的迭代器
    int num = 0;    //累加计数, 因为当删除了一个元素后, 新列表与原列表将不同
    for (i_rowList=rowList.begin(); i_rowList!=rowList.end(); ++i_rowList) {
        fileList.removeAt((*i_rowList)-num);
        num++;
    }
    updateTable();  //更新表格显示
}
//信号-槽 单击-开始转换按钮
void MainWindow::on_btn_startChange_clicked()
{
    nameDest_2_pathDest();  //生成path_dest
    int num = 0;    //记录处理到哪行
    QList<FileData>::iterator i_fileList;  //file_list迭代器
    for (i_fileList=fileList.begin(); i_fileList!=fileList.end(); ++i_fileList) {
        bool is_ok;
        if (!((*i_fileList).pathDest.isEmpty())) { //目标路径非空, 重命名
            is_ok = QFile::rename((*i_fileList).pathSrc, (*i_fileList).pathDest); //重命名
        } else { //目标路径为空, 不进行重命名
            is_ok = false;
        }
        //在表格中显示
        if (is_ok) { //重命名成功
            list_model->setItem(num, 3, new QStandardItem(QString("Yes")));
        } else { //重命名失败
            list_model->setItem(num, 3, new QStandardItem(QString("No")));
        }
        num++;
    }
}
//信号-槽 单击-清除记录按钮
void MainWindow::on_btn_detetRecord_clicked()
{
    //qDebug() << "clear";
    int length = fileList.length(); //获得列表中元素个数
    QList<FileData> tmp_list;  //临时保存表格中重命名失败的元素
    for (int i=0; i<length; i++) { //遍历表格
        QModelIndex index = list_model->index(i, 3);
        QVariant is_ok =  list_model->data(index);
        if (is_ok.toString() != "Yes") { //重命名失败了
            FileData tmp = fileList.at(i);
            tmp_list << tmp;
        }
    }
    fileList.clear();  //清除列表
    QList<FileData>::iterator i_tmpList; //tmp_list 的迭代器
    for (i_tmpList=tmp_list.begin(); i_tmpList!=tmp_list.end(); ++i_tmpList) {
        fileList << (*i_tmpList);
    }
    updateTable();  //更新表格显示
}

//单击 生成新名字 按钮. 根据命名规则,生成新名字, 并更新表格显示
void MainWindow::on_btn_makeNewName_clicked()
{
    rowList_update();   //获取当前多选

    QString nameRule = ui->iLineEdit_nameRule->text();  //命名规则
    int bitNum = ui->iSpinBox_bitNum->value();  //位数
    int addVal = ui->iSpinBox_addVal->value();  //增量
    int beginNum = ui->iLineEdit_beginVal->text().toInt();   //初始数字

    QList<int>::iterator i_rowList; // rowList 列表的迭代器
    for (i_rowList=rowList.begin(); i_rowList!=rowList.end(); ++i_rowList) {
        QString& srcName = fileList[*i_rowList].nameSrc;
        QString& destName = fileList[*i_rowList].nameDest;
        destName.clear();   //先清除
        QString::iterator i_nameRule; //命名规则字符串的迭代器
        for (i_nameRule=nameRule.begin(); i_nameRule!=nameRule.end(); ++i_nameRule) { //遍历整个命名规则字符串
            //qDebug() << "QString: " << (*i_nameRule);
            if (*i_nameRule == '*') {   //原文件名
                destName += srcName;
            } else if (*i_nameRule == '#') {   //递增的数字
                if (ui->iCheckBox_completionBit->isChecked()) { //补全位数
                    destName += QString("%1").arg(beginNum, bitNum, 10, QChar('0'));
                } else { //不补全位数
                    destName += QString::number(beginNum);
                }
                beginNum += addVal;
            } else { //其他, 原样输出
                destName += *i_nameRule;
            }
        }
    }
    updateTable();  //更新表格显示
}
//槽函数 表格行内容被修改
//oldModelIndex 与 newModelIndex 内容相同
void MainWindow::tabRowValueChanged(const QModelIndex &oldModelIndex, const QModelIndex &newModelIndex)
{
    int rowNum = newModelIndex.row();       //行
    int columnNum= newModelIndex.column();  //列
    switch (columnNum) {
        case 0:     //第0列, 原文件名, 不可修改
            if (fileList[rowNum].nameSrc == newModelIndex.data().toString()) { //新旧内容一样, 不修改列表中数据
                return ;
            }
            break;
        case 1:     //第1列, 新文件名, 可修改
            if (fileList[rowNum].nameDest == newModelIndex.data().toString()) { //新旧内容一样, 不修改列表中数据
                return ;
            }
            //两次内容不一样, 修改列表中的数据
            fileList[rowNum].nameDest = newModelIndex.data().toString();  //更改列表中的数据
            break;
        case 2: //第2列, 文件后缀, 是否可修改取决于 ui->iCheckBox_changeFileType 是否被勾选
            if (fileList[rowNum].fileType == newModelIndex.data().toString()) { //新旧内容一样, 不修改列表中数据
                return ;
            }
            //两次内容不一样, 修改列表中的数据
            if (ui->iCheckBox_changeFileType->isChecked()) { //修改文件类型
                fileList[rowNum].fileType = newModelIndex.data().toString();  //更改列表中的数据
            }
            break;
        case 3: //第3列, 重命名成功状态, 不可修改
            return ;
            break;
    }
    updateTable();  //更新表格显示
}
